#include<string.h>
#include<iostream>
#include<pthread.h>
#include<unistd.h>

using namespace std;
/*
这个时候涉及到了互斥量的接口，首先要初始化互斥量
这里有两种初始化方法，第一种方法叫做静态分配，第二种方法叫做
动态分配

静态分配：
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
动态分配：
pthread_mutex_init(pthread_mutex_t mutex,const pthread_mutex
)

互斥量的销毁，使用动态分配的互斥量是不需要进行销毁的，如果
销毁以后要确保后续不会再有线程尝试着加锁
互斥量加锁和解锁：
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
成功返回0，失败返回错误码
*/
//那么这个时候使用互斥量对售票系统进行以下改进

/*
互斥量也叫做锁
linux 线程互斥==========================================
这个概念非常重要，一定要彻底掌握
    临界资源：多执行流共享的代码，就叫做临界区
    互斥：任何时刻，互斥保证有且只有一个执行流进入临界区，访问
临界资源，通常对临界资源其保护作用
    原子性：不会被任何调度机制打断的操作，该操作只有两态，完成
和未完成，汇编语言上面体现为只有一条语句

互斥量mutex
大部分情况下，线程使用的数据都是局部变量，，变量的地址空间
在线程的线程栈空间内，这种情况下，变量只属于单个线程私有，
其他线程是无法获得的，这也就是为什么
pthread_exit(void* value_ptr)当中的指针只允许指向malloc
；开辟出来的空间地址和全局变量，否则指针指向的线程退出状态
无法与其他进程共享，退出状态也会被保存在这样的指针当中
在线程等待的时候可以获得，其他线程也可以获得


================================================
多线程并发的操作共享变量有些时候会带来一些问题
*/
// int tickets=100;
// void* threadRoutine(void* args)
// {
//     while(true)
//     {
//         if(tickets > 0)
//         {
//             cout<<args<<"send "<<tickets<<"tickets"<<endl;
//             usleep(1);
//             tickets--;
//         }
//         else
//         {
//             break;
//         }
//     }
//     return nullptr;
// }
// int main()
// {
//     pthread_t t1,t2,t3;
//     pthread_create(&t1,nullptr,threadRoutine,(void*)"thread 1");
//     pthread_create(&t2,nullptr,threadRoutine,(void*)"thread 1");
//     pthread_create(&t3,nullptr,threadRoutine,(void*)"thread 1");

//     pthread_join(t1,nullptr);
//     pthread_join(t2,nullptr);
//     pthread_join(t3,nullptr);

//     return 0;
// }
// int tickets=100;
// void* threadRoutine(void* args)
// {
//     char* who=(char*)args;
//     while(true)
//     {
//         if(tickets > 0)
//         {
//             usleep(100);
//             cout<<who<<"send "<<tickets<<" "<<"tickets"<<endl;
//             tickets--;
//         }
//         else
//         {
//             break;
//         }
//     }
//     return nullptr;
// }

// int main()
// {
//     pthread_t t1,t2,t3,t4;

//     pthread_create(&t1,nullptr,threadRoutine,(void*)"thread 1");
//     pthread_create(&t2,nullptr,threadRoutine,(void*)"thread 2");
//     pthread_create(&t3,nullptr,threadRoutine,(void*)"thread 3");
//     pthread_create(&t4,nullptr,threadRoutine,(void*)"thread 4");

//     pthread_join(t1,nullptr);
//     pthread_join(t2,nullptr);
//     pthread_join(t3,nullptr);
//     pthread_join(t4,nullptr);
    
//     return 0;
// }


//===================================线程的分离：
/*
默认的情况下，新建的线程是需要主线程主动的join资源，他们的资源
才会释放的，如果主线程不对从线程进行join会造成无法释放资源
从而导致内存泄漏。
    当然如果主线程不关心从线程的退出状态，当从线程退出的时候
他们可以自动释放资源那么这个时候主从线程之间就是分离的，因为
主线程是不关心从线程的退出状态的

int pthread_detatch(pthread_t tid)
//可以是某线程对其他线程的分离，也可以是线程自己的分离
*/

// void* thread_run(void* args)
// {
//     pthread_detach(pthread_self());
//     cout<<(char*)args<<endl;
//     return nullptr;
// }
// int main()
// {
//     pthread_t tid;
//     int flag=pthread_create(&tid,nullptr,thread_run,(void*)"thread run");
//     if(flag != 0)
//     {
//         cout<<"create fail"<<endl;
//         return 1;
//     }
//     int check=0;
//     sleep(3);
//     int flag2=pthread_join(tid,nullptr);
//     if(flag2 == 0)
//     {
//         cout<<"wait success"<<endl;
//         check=0;
//     }
//     else
//     {
//         cout<<"wait fail"<<endl;
//         check=1;
//     }
//     return check;
// }

// void* thread_run(void* args)
// {
//     pthread_detach(pthread_self());
//     cout<<(char*)args<<endl;
//     return nullptr;
// }
// int main()
// {
//     pthread_t tid;
//     int res=pthread_create(&tid,nullptr,thread_run,(void*)"thread run");
//     cout<<"create thread error"<<endl;
//     if(res != 0)
//     {
//         perror("pthread_create");
//         return 1;
//     }

//     int ret=0;
//     sleep(1);
//     //先让线程之间先进行分离，在让主线程进行等待
//     int res2=pthread_join(tid,nullptr);
//     if(res2 == 0)
//     {
//         cout<<"pthread wait success"<<endl;
//         ret=0;
//     }
//     else
//     {
//         cout<<"thread wait failed"<<endl;
//         ret=1;
//     }
//     return ret;
// }
/*
//=========================线程的创建、等待、取消
以下三类函数基本掌握
void pthread_cancel(pthread_t tid)
void _pthread_create(pthread_t* tid,void* value_ptr)
void pthread_exit(void* value_ptr)
int pthread_join(pthread_t tid,void** value_ptr)
*/
// void* thread1(void* args)
// {
//     cout<<"thread 1 returning"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=1;
//     return (void*)p;
// }
// void* thread2(void* args)
// {
//     cout<<"thread 2 exiting"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=2;
//     //指针会自动被保留
//     pthread_exit((void*)p);
// }
// void* thread3(void* args)
// {
//     while(true)
//     {
//         cout<<"thread 3 running"<<endl;
//         sleep(1);
//     }
//     return nullptr;
// }
// int main()
// {
//     pthread_t tid;
//     void* ret;

//     pthread_create(&tid,nullptr,thread1,nullptr);
//     pthread_join(tid,&ret);
//     printf("thread return : thread id:%X,thread code:%d",tid,*(int*)ret);
//     free(ret);

//     pthread_create(&tid,nullptr,thread2,nullptr);
//     pthread_join(tid,&ret);
//     printf("thread return : thread id:%X,thread code:%d",tid,*(int*)ret);
//     free(ret);

//     pthread_create(&tid,nullptr,thread3,nullptr);
//     sleep(3);
//     pthread_cancel(tid);
//     pthread_join(tid,&ret);
//     if(ret == PTHREAD_CANCELED)
//     {
//         printf("thread return:thread id:%X,thread code:PTHREAD_CANCELED",tid);
//     }
//     else
//     {
//         printf("thread return:thread id:%X,thread code:NULL",tid);
//     }
//     return 0;
// }
// void* thread1(void* args)
// {
//     cout<<"thread 1 returning"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=1;
//     return (void*)p;
// }
// void* thread2(void* args)
// {
//     cout<<"thread 2 exiting"<<endl;
//     int* p=(int*)malloc(sizeof(int));
//     *p=2;
//     return (void*)p;
// }
// void* thread3(void* args)
// {
//     while(true)
//     {
//         cout<<"thread 3 running"<<endl;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     pthread_t tid;
//     void* ret;

//     pthread_create(&tid,nullptr,thread1,nullptr);
//     pthread_join(tid,&ret);
//     printf("thread return:thread id:%X,thread code:%d",tid,*(int*)ret);
//     cout<<endl;
//     free(ret);

//     pthread_create(&tid,nullptr,thread2,nullptr);
//     pthread_join(tid,&ret);
//     printf("thread return:thread id:%X,thread code:%d",tid,*(int*)ret);
//     cout<<endl;
//     free(ret);

//     pthread_create(&tid,nullptr,thread3,nullptr);
//     sleep(3);
//     pthread_cancel(tid);
//     pthread_join(tid,&ret);
//     if(ret == PTHREAD_CANCELED)
//     {
//         printf("thread return: thread id:%X,thread code:PTHREAD_CANCELED",tid);
//         cout<<endl;
//     }
//     else
//     {
//         printf("thread return:thread id:%X,thread code:NULL",tid);
//         cout<<endl;
//     }
//     return 0;
// }